package com.pai4j.user.service.analytics;

import com.pai4j.domain.vo.request.AccountRelationAnalyticsRequestVO;
import com.pai4j.domain.vo.response.AccountRelationAnalyticsVO;
import com.pai4j.domain.vo.response.AccountRelationTrendVO;
import com.pai4j.user.repository.dao.IFriendDAO;
import com.pai4j.user.service.relation.FriendFollowService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 账号关系数据分析服务
 * 提供粉丝和关注数据的多维度统计分析
 *
 * @author PAI4J
 */
@Slf4j
@Service
public class AccountRelationAnalyticsService {

    @Autowired
    private IFriendDAO friendDAO;

    @Autowired
    private FriendFollowService friendFollowService;

    private static final int STATUS_FOLLOWING = 1;
    private static final int STATUS_UNFOLLOW = 0;
    private static final int DEFAULT_DAYS = 7;
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 获取账号关系数据分析报告
     *
     * @param request 分析请求参数
     * @return 数据分析结果
     */
    public AccountRelationAnalyticsVO getAnalytics(AccountRelationAnalyticsRequestVO request) {
        Assert.hasText(request.getAccount(), "account cannot be empty");

        // 参数处理
        String account = request.getAccount();
        Integer days = request.getDays() != null ? request.getDays() : DEFAULT_DAYS;
        Boolean includeCumulativeTrend = request.getIncludeCumulativeTrend() != null ? request.getIncludeCumulativeTrend() : false;

        // 计算时间范围
        Date endDate = getEndOfToday();
        Date startDate = getDateBefore(days);

        log.info("开始生成账号关系数据分析报告: account={}, days={}, startDate={}, endDate={}",
                account, days, DATE_FORMAT.format(startDate), DATE_FORMAT.format(endDate));

        // 构建分析结果
        AccountRelationAnalyticsVO analytics = AccountRelationAnalyticsVO.builder()
                .account(account)
                .days(days)
                .startDate(DATE_FORMAT.format(startDate))
                .endDate(DATE_FORMAT.format(endDate))
                .build();

        try {
            // 1. 获取当前总数
            Long totalFollowers = friendFollowService.getFollowersCount(account);
            Long totalFollowing = friendFollowService.getFollowingCount(account);
            analytics.setTotalFollowers(totalFollowers);
            analytics.setTotalFollowing(totalFollowing);

            // 2. 统计期间新增和取关数据
            Long newFollowers = friendDAO.countNewFollowersByDateRange(account, STATUS_FOLLOWING, startDate, endDate);
            Long unfollows = friendDAO.countUnfollowsByDateRange(account, STATUS_UNFOLLOW, startDate, endDate);
            Long newFollowing = friendDAO.countNewFollowingByDateRange(account, STATUS_FOLLOWING, startDate, endDate);

            analytics.setNewFollowers(newFollowers);
            analytics.setUnfollows(unfollows);
            analytics.setNewFollowing(newFollowing);

            // 3. 计算净增长和增长率
            Long followersNetGrowth = newFollowers - unfollows;
            analytics.setFollowersNetGrowth(followersNetGrowth);

            // 粉丝增长率 = (期间净增长 / 期初粉丝数) * 100%
            Long initialFollowers = totalFollowers - followersNetGrowth;
            Double followersGrowthRate = calculateGrowthRate(followersNetGrowth, initialFollowers);
            analytics.setFollowersGrowthRate(followersGrowthRate);

            // 关注增长率
            Long initialFollowing = totalFollowing - newFollowing;
            Double followingGrowthRate = calculateGrowthRate(newFollowing, initialFollowing);
            analytics.setFollowingGrowthRate(followingGrowthRate);

            // 4. 计算日均新增
            Double avgDailyNewFollowers = calculateAverage(newFollowers, days);
            Double avgDailyNewFollowing = calculateAverage(newFollowing, days);
            analytics.setAvgDailyNewFollowers(avgDailyNewFollowers);
            analytics.setAvgDailyNewFollowing(avgDailyNewFollowing);

            // 5. 粉丝/关注比率
            Double followersToFollowingRatio = calculateRatio(totalFollowers, totalFollowing);
            analytics.setFollowersToFollowingRatio(followersToFollowingRatio);
            analytics.setIsQualityAccount(totalFollowers > totalFollowing);

            // 6. 获取趋势数据
            List<AccountRelationTrendVO> followersTrend = getFollowersTrend(account, startDate, endDate);
            List<AccountRelationTrendVO> followingTrend = getFollowingTrend(account, startDate, endDate);
            analytics.setFollowersTrend(followersTrend);
            analytics.setFollowingTrend(followingTrend);

            // 7. 获取累计趋势数据（可选，查询较慢）
            if (includeCumulativeTrend) {
                List<AccountRelationTrendVO> followersCumulativeTrend = getCumulativeFollowersTrend(account, days);
                analytics.setFollowersCumulativeTrend(followersCumulativeTrend);
            }

            log.info("账号关系数据分析报告生成成功: account={}, totalFollowers={}, newFollowers={}, followersGrowthRate={}%",
                    account, totalFollowers, newFollowers, followersGrowthRate);

        } catch (Exception e) {
            log.error("生成账号关系数据分析报告失败: account={}", account, e);
            throw new RuntimeException("数据分析失败", e);
        }

        return analytics;
    }

    /**
     * 获取粉丝增长趋势数据
     */
    private List<AccountRelationTrendVO> getFollowersTrend(String account, Date startDate, Date endDate) {
        List<Object[]> results = friendDAO.getFollowersTrendByDay(account, STATUS_FOLLOWING, startDate, endDate);
        return convertToTrendVO(results);
    }

    /**
     * 获取关注增长趋势数据
     */
    private List<AccountRelationTrendVO> getFollowingTrend(String account, Date startDate, Date endDate) {
        List<Object[]> results = friendDAO.getFollowingTrendByDay(account, STATUS_FOLLOWING, startDate, endDate);
        return convertToTrendVO(results);
    }

    /**
     * 获取粉丝累计趋势数据
     */
    private List<AccountRelationTrendVO> getCumulativeFollowersTrend(String account, Integer days) {
        List<Object[]> results = friendDAO.getCumulativeFollowersTrend(account, STATUS_FOLLOWING, days);
        return results.stream()
                .map(row -> AccountRelationTrendVO.builder()
                        .date(row[0] != null ? row[0].toString() : "")
                        .cumulativeCount(row[1] != null ? ((Number) row[1]).longValue() : 0L)
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * 转换查询结果为趋势VO
     */
    private List<AccountRelationTrendVO> convertToTrendVO(List<Object[]> results) {
        return results.stream()
                .map(row -> AccountRelationTrendVO.builder()
                        .date(row[0] != null ? row[0].toString() : "")
                        .count(row[1] != null ? ((Number) row[1]).longValue() : 0L)
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * 计算增长率（百分比）
     * 增长率 = (增长量 / 基数) * 100
     */
    private Double calculateGrowthRate(Long growth, Long base) {
        if (base == null || base == 0) {
            return growth != null && growth > 0 ? 100.0 : 0.0;
        }
        if (growth == null) {
            growth = 0L;
        }
        return BigDecimal.valueOf(growth)
                .multiply(BigDecimal.valueOf(100))
                .divide(BigDecimal.valueOf(base), 2, RoundingMode.HALF_UP)
                .doubleValue();
    }

    /**
     * 计算平均值
     */
    private Double calculateAverage(Long total, Integer days) {
        if (total == null || days == null || days == 0) {
            return 0.0;
        }
        return BigDecimal.valueOf(total)
                .divide(BigDecimal.valueOf(days), 2, RoundingMode.HALF_UP)
                .doubleValue();
    }

    /**
     * 计算比率
     */
    private Double calculateRatio(Long numerator, Long denominator) {
        if (denominator == null || denominator == 0) {
            return numerator != null && numerator > 0 ? Double.MAX_VALUE : 0.0;
        }
        if (numerator == null) {
            numerator = 0L;
        }
        return BigDecimal.valueOf(numerator)
                .divide(BigDecimal.valueOf(denominator), 2, RoundingMode.HALF_UP)
                .doubleValue();
    }

    /**
     * 获取N天前的日期（00:00:00）
     */
    private Date getDateBefore(int days) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, -days);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取今天结束时间（23:59:59）
     */
    private Date getEndOfToday() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }
}
